GraphQL은 객체의 특정 필드 값을 받아오기 위해 사용할 수 있다. 쿼리와 결과는 같은 구조를 띈다.
예를 들어, 아래의 쿼리는
{
hero {
name
# 주석은 이런식으로 달 수 있다
# 아래처럼 오브젝트에 대한 쿼리를 날릴 수도 있다.
friends {
name
}
}
}
이런 결과를 가져올 수 있다.
name
이라는 필드는 R2-D2
라는 문자열을 반환한다.
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
REST와 다르게 각 필드과 오브젝트는 각각 인자를 받을 수 있다.
{
human(id: "1000") {
name
# unit은 METER / FOOT의 enum 타입을 사용
height(unit: FOOT)
}
}
결과:
{
"data": {
"human": {
"name": "Luke Skywalker",
"height": 5.6430448
}
}
}
그럼 같은 필드에 대해 각각 다른 인자를 넘긴 결과값을 받아오기 위해서는 쿼리를 어떻게 짤까?
별명을 이용하면 된다.
{
empireHero: hero(episode: EMPIRE) {
name
}
jediHero: hero(episode: JEDI) {
name
}
}
쿼리가 복잡해지면 인자만 다를 때 복잡한 쿼리를 계속 적어줘야한다. 중복되는 쿼리를 사용할 수 없을까?
그럴 때 fragment를 선언하여 가져오려는 쿼리를 dry하게 작성할 수 있다.
{
leftComparison: hero(episode: EMPIRE) {
...comparisonFields
}
rightComparison: hero(episode: JEDI) {
...comparisonFields
}
}
fragment comparisonFields on Character {
name
appearsIn
friends {
name
}
}
실습: https://beta.pokeapi.co/graphql/console/
피카츄(pikachu), 파이리(charmander), 꼬부기(squirtle)의 키, 몸무게, 기술의 이름(5 개까지)를 반환해보자.
query 작성시에 값을 정의한다.
# $first라는 변수에 Int형 값 3을 저장
query HeroComparison($first: Int = 3) {
leftComparison: hero(episode: EMPIRE) {
...comparisonFields
}
rightComparison: hero(episode: JEDI) {
...comparisonFields
}
}
fragment comparisonFields on Character {
name
# 여기서 이렇게 정의한 변수를 사용 가능함
friendsConnection(first: $first) {
totalCount
edges {
node {
name
}
}
}
}
query 작성시에는 query
키워드와 query의 이름을 지어줘야한다. 위의 몇몇 예제처럼 생략할 수도 있지만 대체로 햇갈리지 않게 하기 위해 적어준다.
키워드 종류는 query
, mutation
, subcription
이 있다.
query에 제공하는 인자 값은 주로 가변적일 것이다. 그러므로 인자 값을 직접 쿼리에 작성하는 것은 별로 도움이 되지 않는다. 이때 변수를 정의하여 사용한다.
$변수명
형태로 교체한다.$변수명
을 query에 선언한다.변수명: 값
JSON 형태로 전달모든 변수는 스칼라 값이거나 ,enum, 혹은 입력 객체형이어야 한다.
존재하는 타입형: Int
, Boolean
, String
, DateTime
, Float
배열로 작성하려면: [Int]
이런식으로 쓸 수 있다.
변수 형 옆에 !
를 붙여서 필수로 필요한 값임을 명시할 수 있다.
변수 형 옆에 = '기본값'
할 수 있다.
특정 조건에 의해 내부 쿼리 구조를 다르게 해야할 때가 있다.
@include(if: boolean)
을 이용하여 결과에 포함할지 결정@skip(if: boolean)
을 이용하여 결과에 포함하지 않을지 결정query Hero($episode: Episode, $withFriends: Boolean!) {
hero(episode: $episode) {
name
friends @include(if: $withFriends) {
name
}
}
}
실습: https://beta.pokeapi.co/graphql/console/
피카츄(pikachu), 파이리(charmander), 꼬부기(squirtle)의 키, 몸무게, 기술의 이름(N 개까지)를 반환해보자.
서버의 데이터를 조작해야할 때 사용
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
params
{
"ep": "JEDI",
"review": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
반환되는 것은 갱신 후의 데이터이다.
$review
변수에 할당된 것은 scalar
값이 아닌 input object type
임에 유의하자.
자세한 사항은 [[GraphQL - Schemas and Types]]에서 알아보자
query와 mutation의 공통점은 모두 여러개의 field를 가지질 수 있다는 점이다.
차이점은 query는 병렬로 실행될 수 있지만 mutation은 그렇지 않다는 점이다. 이로써 race condition을 방지할 수 있다.
interface나 union type인 field를 반환할 때 사용
query HeroForEpisode($ep: Episode!) {
# Character는 Droid거나 Human임
hero(episode: $ep) {
name
# Droid에만 있는 필드
... on Droid {
primaryFunction
}
# Human에만 있는 필드
... on Human {
height
}
}
}
어떤 타입을 받을지 모를때 __typename
이라는 meta field를 아무곳에서 요청할 수 있다.
search(text: "an") {
__typename
... on Human {
name
}
... on Droid {
name
}
... on Starship {
name
}
}
}
결과
{
"data": {
"search": [
{
"__typename": "Human",
"name": "Han Solo"
},
{
"__typename": "Human",
"name": "Leia Organa"
},
{
"__typename": "Starship",
"name": "TIE Advanced x1"
}
]
}
}
-> [[GraphQL - Schemas and Types]]